iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0
Modern Web

Three.js 學習日誌系列 第 4

Day3 - 進入Three.js的領域

  • 分享至 

  • xImage
  •  

Day3 - 進入Three.js的領域

這裡是「Three.js學習日誌」的第3篇,本篇的主旨是透過試做一個Three.js的Hello World案例,來讓讀者對於Three.js有基本的認識,這系列的文章假設讀者看得懂javascript,並且有Canvas 2D Context的相關知識。

初次來到新世界

第一次使用three.js,尤其是那些沒有使用過3D建模軟體的人,多半會對每一個基本操作都有不小的疑問,畢竟three.js提供的API種類繁多,而且光看官方文件又有一大堆的專有名詞,讓人頭昏眼花。

建議初學者可以先去玩過隨便一款3D建模軟體(首推Blender),畢竟菜鳥如小弟我就是這麼做的。

這邊我們會先做一個簡單的Hello World,並且一步一步講解每個步驟的用意,目的是希望可以讓讀者試試味道,並且對Three.js產生基本的認識。


0. 這個Hello World的目標

這個Hello World的目標是要畫出來一個轉動的立方體(如圖)。

轉動方塊

codepen連結:https://codepen.io/mizok/pen/XWqRyPQ?editors=0010

1. 導入npm module

為了求快速,在這個案例中我們先用codepen搭配https://cdn.skypack.dev提供的CDN來取得three.js的module。

import {
  ... //這邊接著會引入必要的模組
} from "https://cdn.skypack.dev/three";

2. 建立Scene實例

Scene這個類別按字面解釋就是,他有點像是世界的概念,當我們要去把一個three.js的程序render出畫面,基本上就是要去渲染這個裡面所有物件構成的圖像。

import {
  Scene
} from "https://cdn.skypack.dev/three";

function main (){
   const scene = new Scene();
}

main();

3. 建立Renderer(渲染器)實例

three.js 其實有提供很多種類的renderer,但是最常用的基本上還是WebGLRenderer。渲染器顧名思義當然是用來渲染用的,他本身會提供一個render方法,可以用來把一個Scene中的圖像渲染出來。

這邊我們順手設置antialias(反鋸齒)和alpha(開啟透明通道)兩個option。

antialias(反鋸齒)是一種特殊的演算法,他可以用來柔化圖形邊緣因為像素顆粒太明顯而形成的鋸齒狀瑕疵

而之所以要開啟alpha(透明通道)是因為three.js預設是不渲染透明通道的(也就是背景會全黑)。

還記得我們在前面演示過webgl清除畫布的方法嗎? 就是藉由填入特定的clearColor來達到清除的效果,清除色是可以設定為具有透明度的顏色的,所以假如我們要讓canvas背景為透明無色,那就必須要:

  • 開放alpha通道
  • 清除色的透明度必須是0

設置完renderer實例之後要記得把renderer.domElement放到dom tree裡面(domElement其實就是canvas)

import {
  Scene
  WebGLRenderer
} from "https://cdn.skypack.dev/three";

function main (){
   const scene = new Scene();
   const renderer = new WebGLRenderer({
    antialias: true,
    alpha: true
  });
  document.body.append(renderer.domElement);
}

main();

4. 設定畫布大小與Viewport,還有清除色

這邊應該就沒甚麼特別的,Viewport其實就是我們在上一篇介紹過的gl.viewport方法,也就是畫布範圍的映射。

畫布大小與Viewport,還有清除色的設定方法都可以從renderer物件底下取得,他們分別是renderer.setSize,renderer.setViewport,還有renderer.setClearColor

import {
  Scene,
  WebGLRenderer,
} from "https://cdn.skypack.dev/three";

function main() {
  const scene = new Scene();
  const renderer = new WebGLRenderer({
    antialias: true,
    alpha: true
  });

  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
  renderer.setClearColor(new Color(0,0,0),0);
}

main();

5. 建立Camera實例

沒有使用過3D建模軟體的人可能會不太明白Camera的概念。

在3D建模軟體中,Camera的用途就是把景物"照"下來。

我們前面有提到,three.js要渲染畫面的時候要透過rendererrender方法,我們除了要告訴renderer是要渲染哪一個以外,還得告訴他是要使用那個裡面的哪一台Camera,這樣才可以取得那台Camera照出來的圖像。

img

這張圖片(來源)稍微有點不正確,其實成像畫面不應該呈現在Near Clip plane上面。

Camera(相機)有很多種類型,每一種都各有各的使用場景。

在這邊我們使用PerspectiveCamera這個類所生成的相機實例,所謂的"Perspective"就是"透視法",所謂的"透視法"是一種繪畫的技法,用來把實際的三維空間的座標點,投射到二維平面上。

關於透視法,我去年有寫過一篇3維投影相關的技術文章,可以參考這裡

PerspectiveCamera這個類必須要傳入4個參數,分別是FOV畫面長寬比近平面遠平面

img

圖片來源:computergraphics.stackexchange

  • FOV: 也就是攝影機的水平視角(Field of View),基本上所有的光學成像儀器都會有FOV的設置,以人眼來講,人眼的FOV大約是120度,超出視角的東西就不會在成像畫面中顯示出來。
  • 畫面長寬比:就是預期成像畫面的長寬比。
  • 近平面/遠平面:其實就是一種範圍限制,攝影機不會把比近平面還要近,或是位置超出遠平面的東西照進去畫面。

另外順帶一提,three.jsPerspectiveCamera模仿的是現實生活中的35mm相機,也就是預設具備35mm的焦距,再換句話說就是攝影機到成像平面(上圖的z-projection平面)的預設距離為35單位長。

初始化過PerspectiveCamera的實例之後,記得要add進去Scene裡面。

import {
  Scene,
  WebGLRenderer,
  PerspectiveCamera
} from "https://cdn.skypack.dev/three";

function main() {
  ...
  
  const camera = new PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  
  scene.add(camera)
}

main();


上一篇
Day2 - 從webGL的基礎開始?(二)
下一篇
Day4 - 進入Three.js的領域 - 續
系列文
Three.js 學習日誌31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言